home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1997 May
/
EnigmA AMIGA RUN 18 (1997)(G.R. Edizioni)(IT)[!][issue 1997-05][EAR-CD II].iso
/
earcd
/
util
/
sys
/
msys_1_2.lha
/
Src
/
makelink.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-02-10
|
8KB
|
243 lines
/*
** makelink.c - create filesystem links
** $VER: makelink.c 42.1 (10.2.96)
** Copyright © 1996 Michal Letowski
**
** 42.1 (10.2.96) - initial version
*/
#define __USE_SYSBASE
#include <exec/types.h>
#include <exec/execbase.h>
#include <exec/libraries.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/rdargs.h>
#include <support/types.h>
#include <support/dos.h>
#include <string.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include "makelink.rev.h"
/*
** Constants
*/
#define DOS_NAME "dos.library"
#define DOS_VERN 37L
#define TEMPLATE "FROM/A,TO/A,HARD/S,SOFT/S,FORCE/S"
#define TEST_ERROR -1L
#define TEST_FILE 0L
#define TEST_DIR 1L
/*
** Private structures
*/
struct Options
{
STRPTR opt_From; /* FROM/A */
STRPTR opt_To; /* TO/A */
LBOOL opt_Hard; /* HARD/S */
LBOOL opt_Soft; /* SOFT/S */
LBOOL opt_Force; /* FORCE/S */
}; /* Options */
/*
** Global data
*/
STATIC CONST TEXT VersionString[]=
VERSION(PROG_NAME,PROG_VERSION,PROG_REVISION,PROG_DATE);
/*
** Private functions prototypes
*/
STATIC LONG TestLock(struct Options *opts, BPTR lock, struct Library *DOSBase);
/*
** Public functions
*/
/****** C/MakeLink **********************************************************
*
* NAME
* MakeLink -- create filesystem links. (V42)
*
* SYNOPSIS
* MakeLink Source Target [HARD] [SOFT] [FORCE]
*
* TEMPLATE
* MakeLink "FROM/A,TO/A,HARD/S,SOFT/S,FORCE/S"
*
* FUNCTION
* MakeLink creates links to other files or directories. A link is a
* directory entry that points to other file or directory. There are
* two kinds of links:
* hard links - this link points to an already existing file or
* directory located on the same partition;
* soft links - such links may point to any objects (including
* devices, volumes, and partitions) and as such are
* more flexible.
* MakeLink creates a Source name link that points to Target. HARD
* options (default) indicates that it is a hard link. SOFT option
* indicates a soft link. You can't specify both HARD and SOFT. When
* creating hard links to directories FORCE option must be given.
* MakeLink detects circular (i.e. to parent directories) dependencies
* during creation of hard links and will not create such links.
*
* INPUTS
* Source - name of symbolic link to create.
* Target - name of link target. In case of hard links must be an
* existing directory or file name.
* HARD - indicates hard link (default).
* SOFT - indicates soft link.
* FORCE - this keyword must appears during creation of hard links to
* directories, ignored for soft links.
*
* RESULT
* RETURN_FAIL - if 'dos.library' couldn't be opened or command line
* arguments couldn't be processed or both HARD and SOFT
* options appeared on command line.
* RETURN_ERROR - circular dependency was detected (ERROR_OBJECT_LINKED),
* link couldn't be created or some other error.
* RETURN_OK - if a link was created.
*
* EXAMPLE
* MakeLink SYS:Utilities/More C:PPMore
* ; Creates SYS:Utilities/More file that in reality is the C:PPMore.
* MakeLink DF0.link DF0: SOFT
* ; Creates DF0.link pseudo-directory which points to a disk in
* ; DF0: drive.
* MakeLink Work:Music/Lyrics Work:Docs/Lyrics FORCE
* ; Creates Work:Music/Lyrics directory which points to
* ; Work:Docs/Lyrics
*
* NOTES
* Links (especially soft) are not fully supported in current AmigaDOS
* releases. This is why soft links - even pointing to files - will
* look like directories to most of the programs. Creating soft links
* to handlers (like SPEAK:) may yield very strange results.
* MakeLink is pure and can be made resident.
*
* BUGS
* In FastFileSystem before version 40 when referencing a soft link it
* must be the last part of the path. There is also a bug regarding
* removing the target of the hard link (in FastFileSystem, too).
*
* SEE ALSO
* dos.library/MakeLink().
*
*****************************************************************************
*
*/
LONG MakeLinkCom(VOID)
{
struct ExecBase *SysBase=INITSYSBASE;
struct Library *DOSBase;
struct Options Opts;
struct RDArgs *Args;
BPTR DstLock;
LONG LR,RC=RETURN_FAIL;
/* Open DOS */
unless(DOSBase=OpenLibrary(DOS_NAME,DOS_VERN))
throw2(SetResult2(ERROR_INVALID_RESIDENT_LIBRARY), NO_DOS);
/* Read arguments */
clear(&Opts); /* Clear out buffer */
unless(Args=ReadArgs(TEMPLATE,(LONG *)&Opts,NULL))
throw2(PrintFault(IoErr(),PROG_NAME), NO_ARGS);
if(Opts.opt_Hard && Opts.opt_Soft) /* Check options */
throw2(CauseIoErr(ERROR_TOO_MANY_ARGS,PROG_NAME), BAD_ARGS);
RC=RETURN_ERROR; /* Working a bit... */
/* Do the job */
if(Opts.opt_Soft) /* Softlink */
if(MakeLink(Opts.opt_From,(LONG)Opts.opt_To,LINK_SOFT))
RC=RETURN_OK;
else
PrintFault(IoErr(),Opts.opt_From);
else /* Hardlink (by default!) */
if(DstLock=Lock(Opts.opt_To,SHARED_LOCK)) /* Try to lock destination */
{ /* Locking successfull */
LR=TestLock(&Opts,DstLock,DOSBase); /* Test for circular locks */
if(LR>0 && !Opts.opt_Force)
PutStr("Links to directories require use of the FORCE keyword\n");
elif(LR>=0)
if(MakeLink(Opts.opt_From,DstLock,LINK_HARD))
RC=RETURN_OK; /* Link created - success */
else /* Creation unsuccessfull */
PrintFault(IoErr(),Opts.opt_From); /* Print error message */
UnLock(DstLock); /* Remove lock */
}
else /* No lock on destination */
PrintFault(IoErr(),Opts.opt_To); /* Inform user */
/* Exceptions */
catch(BAD_ARGS, );
catch(NO_ARGS, FreeArgs(Args));
catch(NO_DOS, CloseLibrary(DOSBase));
return(RC);
} /* MakeLinkCom */
/*
** Private functions
*/
/* Returns -1 if error, 0 if file or 1 if directory */
STATIC LONG TestLock(struct Options *opts, BPTR lock, struct Library *DOSBase)
{
CHAR Buffer[MAX_PATH_LEN];
struct FileInfoBlock *FIB;
BPTR L1,L2;
LONG RC=TEST_ERROR; /* To indicate circular link */
if(FIB=AllocDosObject(DOS_FIB,NULL)) /* Try to allocate FileInfoBlock */
{ /* Allocation successfull */
if(Examine(lock,FIB)) /* Try to examine lock */
if(FIB->fib_EntryType>=0) /* Directory check */
{ /* It's a directory */
RC=TEST_DIR; /* Set result to 'dir' */
strcpy(Buffer,opts->opt_From); /* Make a copy of path */
*PathPart(Buffer)='\0'; /* NULL-terminate path */
if(L1=Lock(Buffer,SHARED_LOCK)) /* Try to lock FROM path */
do
{
if(SameLock(L1,lock)==LOCK_SAME) /* Compare lock */
{ /* Lock is the same */
RC=TEST_ERROR; /* Mark loop detection */
CauseIoErr(ERROR_OBJECT_LINKED,opts->opt_To);
L2=NULL; /* To break loop */
}
else /* Lock is different */
L2=ParentDir(L1); /* Go level up */
UnLock(L1); /* Remove old lock */
L1=L2; /* Make old lock a new one */
} while(L1); /* While valid lock */
else
PrintFault(IoErr(),Buffer); /* Print error if impossible */
}
else /* It's a file */
RC=TEST_FILE; /* Set result to 'file' */
else /* Could not examine */
PrintFault(IoErr(),opts->opt_To); /* Print error message */
FreeDosObject(DOS_FIB,FIB); /* Free FileInfoBlock */
}
else /* Allocation unsuccessfull */
PrintFault(IoErr(),PROG_NAME); /* Print error message */
return(RC);
} /* TestLock */